//
// Created by ct on 2021/9/16.
//
# include "lib/common.h"
/*
 用UDP协议发送时，用sendto函数最大能发送数据的长度为：
 65535- IP头(20) - UDP头(8)＝65507字节。
 用sendto函数发送数据时，如果发送数据长度大于该值，则函数会返回错误。
由于IP有最大MTU，因此，
UDP 包的大小应该是 1500 - IP头(20) - UDP头(8) = 1472(Bytes)
TCP 包的大小应该是 1500 - IP头(20) - TCP头(20) = 1460 (Bytes)
 */
#define MAXLINE 4096

int main(int argc, char *argv[]) {
    //  if (argc != 2) { error(1, 0, "usage: udpclient "); }

    int socket_fd;
    socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERV_PORT);
    inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr);

    socklen_t server_len = sizeof(server_addr);
    struct sockaddr *reply_addr;

    reply_addr = malloc(server_len);

    char send_line[MAXLINE], recv_line[MAXLINE + 1];

    socklen_t len;
    int n;

    // https://time.geekbang.org/column/article/118122
    while (fgets(send_line, MAXLINE, stdin) != NULL) {
        int i = strlen(send_line);
        if (send_line[i - 1] == '\n') { send_line[i - 1] = 0; }
        printf("now sending %s\n", send_line);
        // 后面两个参数 to 和 addrlen，表示发送的对端地址和端口等信息。
        size_t rt = sendto(socket_fd, send_line, strlen(send_line), 0, (struct sockaddr *) &server_addr, server_len);
        if (rt < 0) { error(1, errno, "send failed "); }
        printf("send bytes: %zu \n", rt);
        len = 0;
        // 后面两个参数 from 和 addrlen，实际上是返回对端发送方的地址和端口等信息，
        // 这和 TCP 非常不一样，TCP 是通过 accept 函数拿到的描述字信息来决定对端的信息。
        // 另外 UDP 报文每次接收都会获取对端的信息，也就是说报文和报文之间是没有上下文的。
        n = recvfrom(socket_fd, recv_line, MAXLINE, 0, reply_addr, &len);
        if (n < 0) error(1, errno, "recvfrom failed");
        recv_line[n] = 0;
        fputs(recv_line, stdout);
        fputs("\n", stdout);
    }
    exit(0);

}